/**
 * @author liuxin
 * @e-mail lxtobe5@gmail.com
 * @update 2011.12.12
 * @prompt If you find my mistake, please contact with me via my e-mail.
 */
package com.ds
{
	/**
	 * Class that contains static utility methods for rank ordering of data like a Rectangle.
	 */	
	public class RectangleStruct
	{
		private static var _id:int;
		private static var _row:int;
		private static var _col:int;
		private static var _upperEdge:Array;
		private static var _lowerEdge:Array;
		private static var _leftEdge:Array;
		private static var _rightEdge:Array;
		private static var _edge:Array;
		
		/**
		 * Get an array of data id around the parameter id, contains the parameter id. 
		 * Each corner has three data id around,each edge doesn't contain two corners id,
		 * each middle has eight data id.
		 * @param id      Any one of data in rectangle struct.
		 * @return Array  Contains data id around the parameter id.
		 */		
		public static function getAreaID(id:int):Array
		{
			_id = id;
			
			if(topLeftCorner == _id)
				return upperLeftCorner();
			if(topRightCorner == _id)
				return upperRightCorner();
			if(bottomLeftCorner == _id)
				return lowerLeftCorner();
			if(bottomRightCorner == _id)
				return lowerRightCorner();
			if(topLine.indexOf(_id) != -1)
				return inTopLine();
			if(bottomLine.indexOf(_id) != -1)
				return inBottomLine();
			if(leftLine.indexOf(_id) != -1)
				return inLeftLine();
			if(rightLine.indexOf(_id) != -1)
				return inRightLine();
			return [_id-_col-1,_id-_col,_id-_col+1,_id-1,_id,_id+1,_id+_col-1,_id+_col,_id+_col+1];
		}
		
		/**
		 * Get row and col according to the parameter id in rectangle struct.
		 * @param id       Any one of data in rectangle struct.
		 * @return Object  Contains row and col information of the parameter id.
		 */		
		public static function getRanks(id:int):Object
		{
			var rows:int = Math.ceil(id/_col);
			var cols:int = id-(rows-1)*_col;
			return {row:rows,col:cols};
		}
		
		/**
		 * Get the data id according to its row and col in rectangle struct. 
		 * @param rows   Correspond to coordinate x.
		 * @param cols   Correspond to coordinate y.
		 * @return int   Get the id.
		 */		
		public static function getRankID(rows:int,cols:int):int
		{
			return (rows-1)*_col+cols;
		}
		
		public static function setRanks(row:int,col:int):void
		{
			if(row<=0&&col<=0)
				error();
			_row = row;
			_col = col;
		}
		
		public static function get row():int
		{
			return _row;
		}
		
		public static function get col():int
		{
			return _col;
		}
		
		public static function get topLeftCorner():int
		{
			return 1;
		}
		
		public static function get topRightCorner():int
		{
			return _col;
		}
		
		public static function get bottomLeftCorner():int
		{
			return (_row-1)*_col+1;
		}
		
		public static function get bottomRightCorner():int
		{
			return _row*_col;
		}
		
		public static function get corner():Array
		{
			return [1,_col,(_row-1)*_col+1,_row*_col];
		}
		
		public static function get topLine():Array
		{
			if(_upperEdge == null)
			{
				_upperEdge = [];
				for (var i:int = 1; i <= _col; i++) 
				{
					_upperEdge.push(i);
				}
				_upperEdge = _upperEdge.slice(1,-1);
			}
			return _upperEdge;
		}
		
		public static function get bottomLine():Array
		{
			if(_lowerEdge == null)
			{
				_lowerEdge = [];
				for (var i:int = 1; i <= _col; i++) 
				{
					_lowerEdge.push((_row-1)*_col+i);
				}
				_lowerEdge = _lowerEdge.slice(1,-1);
			}
			return _lowerEdge;
		}
		
		public static function get leftLine():Array
		{
			if(_leftEdge == null)
			{
				_leftEdge = [];
				for (var j:int = 1; j <= _row; j++)
				{
					_leftEdge.push((j-1)*_col+1);
				}
				_leftEdge = _leftEdge.slice(1,-1);
			}
			return _leftEdge;
		}
		
		public static function get rightLine():Array
		{
			if(_rightEdge == null)
			{
				_rightEdge = [];
				for (var j:int = 1; j <= _row; j++)
				{
					_rightEdge.push(j*_col);
				}
				_rightEdge = _rightEdge.slice(1,-1);
			}
			return _rightEdge;
		}
		
		public static function get line():Array
		{
			trace(_edge);
			
			if(_edge == null)
			{
				_edge = [];
				_edge = _edge.concat(topLine);
				for (var i:int = 0; i < _row-2; i++) 
				{
					_edge.push(leftLine[i]);
					_edge.push(rightLine[i]);
				}
				_edge = _edge.concat(bottomLine);
			}
			return _edge;
		}
		
		public static function get total():int
		{
			return _row*_col;
		}
		
		private static function upperLeftCorner():Array
		{
			return [_id,_id+1,_id+_col,_id+_col+1];
		}
		
		private static function upperRightCorner():Array
		{
			return [_id-1,_id,_id-1+_col,_id+_col];
		}
		
		private static function lowerLeftCorner():Array
		{
			return [_id-_col,_id-_col+1,_id,_id+1];
		}
		
		private static function lowerRightCorner():Array
		{
			return [_id-_col-1,_id-_col,_id-1,_id];
		}
		
		private static function inTopLine():Array
		{
			return [_id-1,_id,_id+1,_id-1+_col,_id+_col,_id+_col+1];
		}
		
		private static function inBottomLine():Array
		{
			return [_id-_col-1,_id-_col,_id-_col+1,_id-1,_id,_id+1];
		}
		
		private static function inLeftLine():Array
		{
			return [_id-_col,_id-_col+1,_id,_id+1,_id+_col,_id+_col+1];
		}
		
		private static function inRightLine():Array
		{
			return [_id-_col-1,_id-_col,_id-1,_id,_id+_col-1,_id+_col];
		}
		
		private static function error():void
		{
			throw new Error("The value should be available");
		}
	}
}